#include <FileSystem.h>
#include <iostream>
#include <QFileDialog>
#include <QTextStream>
#include <fstream>
#include <streambuf>
#include <sstream>

#include <QMetaProperty>
#include <osg/Geode>
#include <osg/Geometry>
#include <osgDB/WriteFile>
FileSystem* FileSystem::_instance = NULL;

FileSystem::FileSystem()
{
    m_domDocument = new QDomDocument();
}

FileSystem::~FileSystem()
{

}

FileSystem *FileSystem::instance()
{
    if (_instance == NULL)
    {
        _instance = new FileSystem();
    }
    return _instance;
}

void FileSystem::loadFile(const QString& filePath)
{
    QFile file(filePath);
    if(file.open(QIODevice::ReadOnly | QIODevice::Text) == false)
    {
        std::cout<<"load xml filed"<<std::endl;
        return;
    }
    QTextStream in(&file);
    QString xmlFileContext = in.readAll();
    file.close();

    m_domDocument->clear();
    m_domDocument->setContent(xmlFileContext,false);
    //std::cout<<m_domDocument->toString().toStdString()<<std::endl;
}

void FileSystem::loadFileByDialog()
{
    QString file_name = QFileDialog::getOpenFileName(0, "Load File","","*.xml");
    loadFile(file_name);
}

void FileSystem::saveFile(const QString& filePath)
{
    QFile file(filePath);
    file.open(QIODevice::WriteOnly);
    file.close();
    if(file.open(QIODevice::WriteOnly | QIODevice::Text) == false)
    {
        std::cout<<"save xml filed"<<std::endl;
    }
    QTextStream out(&file);
    out << m_domDocument->toString();
    file.close();
}

void FileSystem::saveFileByDialog()
{
    QString file_name = QFileDialog::getSaveFileName(0, "Load File","","*.xml");
    saveFile(file_name);
}

QDomElement FileSystem::getDocDomElement()
{
    return m_domDocument->documentElement();
}

void FileSystem::setDocDomElement(const QDomDocument &domElement)
{
    m_domDocument = new QDomDocument(domElement);
}



QString FileSystem::getDomDocStr()
{
    return m_domDocument->toString();
}

void FileSystem::saveBinaryFile(const QString &filePath, float *doubleArray, int arrayCOunt)
{
    QFile file(filePath);
    file.open(QIODevice::WriteOnly);
    file.close();
    if(file.open(QIODevice::WriteOnly ) == false)
    {
        std::cout<<"save binary filed"<<std::endl;
    }

    QDataStream out(&file);
    //out << QString("the answer is");
    out << (qint32)arrayCOunt;
    for(int i =0 ; i<arrayCOunt; i++)
    {
        out << doubleArray[i];
    }
    file.close();
}

void FileSystem::saveBinaryFile(const QString &filePath, QList<float> &floatArray)
{
    QFile file(filePath);
    file.open(QIODevice::WriteOnly);
    file.close();
    if(file.open(QIODevice::WriteOnly ) == false)
    {
        std::cout<<"save binary filed"<<std::endl;
        return;
    }

    QDataStream out(&file);
    out << (qint32)(floatArray.size());
    for(int i = 0; i< floatArray.size(); i++)
    {
        out<<floatArray.at(i);
    }
    file.close();
}

void FileSystem::saveVec3VectorToOSGFile(const QString &filePath, std::vector<osg::Vec3> &vec3Vector)
{
    osg::ref_ptr<osg::Geode> geodePtr = new osg::Geode;
    osg::ref_ptr<osg::Geometry> geomPtr = new osg::Geometry;
    osg::Vec3Array* vecArray = new osg::Vec3Array;
    for(int i = 0; i < vec3Vector.size(); i++)
    {
        vecArray->push_back(vec3Vector[i]);
    }
    geomPtr->setVertexArray(vecArray);
    geomPtr->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::POINTS, 0,  vec3Vector.size() ));
    geodePtr->addDrawable(geomPtr);

    osgDB::writeNodeFile(*geodePtr, filePath.toStdString());


}

void FileSystem::saveVec3VectorToMatlabFile(const QString &filePath, std::vector<osg::Vec3> &vec3Vector)
{
    QFile data(filePath);
    if (data.open(QFile::WriteOnly | QFile::Truncate))
    {
        QTextStream out(&data);
        for(int i=0; i < vec3Vector.size(); i++)
        {
            osg::Vec3 point = vec3Vector.at(i);
            out <<point.x()<<" "<<point.y()<<" "<<point.z()<<" "<<endl;
        }
    }
}

void FileSystem::saveVec3VectorToMatlabFile2(const QString &filePath, int size)
{
    QFile data(filePath);
    if (data.open(QFile::WriteOnly | QFile::Truncate))
    {
        QTextStream out(&data);
        for(int i=0; i < size; i++)
        {
            out <<0.0<<endl;
        }
    }
}

void FileSystem::readBinaryFile(const QString &filePath, std::vector<float> &floatVec)
{
    QFile file(filePath);

    if(file.open(QIODevice::ReadOnly) == false)
    {
        std::cout<<"FileSystem::readBinaryFile filed"<<std::endl;
        return;
    }


    QDataStream in(&file);
    qint32 arrayCOunt;
    in >> arrayCOunt;
    float floatValue;
    //std::cout<<"FileSystem::readBinaryFIle arrayCOunt"<<arrayCOunt<<std::endl;
    std::cout<<"FileSystem::readBinaryFIle readBinaryFile start"<<std::endl;

    for(int i=0; i < arrayCOunt; i++)
    {
        in >> floatValue;
        floatVec.push_back(floatValue);
    }
    std::cout<<"FileSystem::readBinaryFIle readBinaryFile end valueCount="<<floatVec.size()<<std::endl;

}

void FileSystem::readBinaryFile(const QString &filePath, std::vector<osg::Vec3> &vec3Vector)
{
    QFile file(filePath);

    if(file.open(QIODevice::ReadOnly) == false)
    {
        std::cout<<"FileSystem::readBinaryFile filed"<<std::endl;
        return;
    }

    QDataStream in(&file);
    qint32 arrayCOunt;
    in >> arrayCOunt;
    float floatValue1;
    float floatValue2;
    float floatValue3;
    std::cout<<"FileSystem::readBinaryFIle readBinaryFile start"<<std::endl;
    for(int i=0; i < arrayCOunt; i = i+3)
    {
        in >> floatValue1;
        in >> floatValue2;
        in >> floatValue3;
        vec3Vector.push_back(osg::Vec3(floatValue1,floatValue2, floatValue3 ));
    }
    std::cout<<"FileSystem::readBinaryFIle readBinaryFile end vec3Vector="<<vec3Vector.size()<<std::endl;

}
bool FileSystem::removeFolderContent(const QString &folderDir)
{
    QDir dir(folderDir);
        QFileInfoList fileList;
        QFileInfo curFile;
        if(!dir.exists())  {return false;}//文件不存，则返回false
        fileList=dir.entryInfoList(QDir::Dirs|QDir::Files
                                   |QDir::Readable|QDir::Writable
                                   |QDir::Hidden|QDir::NoDotAndDotDot
                                   ,QDir::Name);
        while(fileList.size()>0)//跳出条件
        {
            int infoNum=fileList.size();
            for(int i=infoNum-1;i>=0;i--)
            {
                curFile=fileList[i];
                if(curFile.isFile())//如果是文件，删除文件
                {
                    QFile fileTemp(curFile.filePath());
                    fileTemp.remove();
                    fileList.removeAt(i);
                }
                if(curFile.isDir())//如果是文件夹
                {
                    QDir dirTemp(curFile.filePath());
                    QFileInfoList fileList1=dirTemp.entryInfoList(QDir::Dirs|QDir::Files
                                                                  |QDir::Readable|QDir::Writable
                                                                  |QDir::Hidden|QDir::NoDotAndDotDot
                                                                  ,QDir::Name);
                    if(fileList1.size()==0)//下层没有文件或文件夹
                    {
                        dirTemp.rmdir(".");
                        fileList.removeAt(i);
                    }
                    else//下层有文件夹或文件
                    {
                        for(int j=0;j<fileList1.size();j++)
                        {
                            if(!(fileList.contains(fileList1[j])))
                                fileList.append(fileList1[j]);
                        }
                    }
                }
            }
        }
        return true;
}
